package com.taikang.system.controller.admin;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import com.taikang.base.cloud.client.CloudStorageClient;
import com.taikang.base.cloud.client.dto.StorageFileVO;
import com.taikang.base.cloud.security.CloudStorageAccessType;
import com.taikang.base.controller.BaseController;
import com.taikang.base.token.TokenValidate;
import com.taikang.base.util.DateUtil;
import com.taikang.system.entity.SysUploadFile;
import com.taikang.system.entity.SysUploadSet;
import com.taikang.system.form.SysUploadFileForm;
import com.taikang.system.service.ISysUploadFileService;
import com.taikang.system.service.ISysUploadSetService;

/**
 * 本地上传
 * @author taikang
 *
 */
@Controller("fileUploadController")
@Scope("prototype")
public class FileUploadController extends BaseController{
	private static final Log logger = LogFactory.getLog(FileUploadController.class); 
	/** 上传文件名 */
	private static final String UPLOAD_FILE_NAME = "uploadFile";
	
	//云存储域名
	@Value("${cloud.storage.doamin}")
	private String cloudStorageDomain;
	//云存储账号
	@Value("${cloud.storage.account.name}")
	private String cloudStorageAccountName;
	//云存储key
	@Value("${cloud.storage.account.key}")
	private String cloudStorageAccountKey;
	
	@Resource(name = "sysUploadSetServiceImpl")
	private ISysUploadSetService sysUploadSetService;
	
	@Resource(name = "sysUploadFileServiceImpl")
	private ISysUploadFileService sysUploadFileService;
	
	/**
	 * 文件云上传
	 */
	@RequestMapping(value = "/uploadFileByCloud.htm", method = RequestMethod.POST)
	@TokenValidate
	public ModelAndView uploadFileByCloud(HttpServletRequest request){
		if(!(request instanceof MultipartHttpServletRequest)){
			return ajaxHTML(Status.error,"无文件上传",null);
		}
		
		try{
			MultipartHttpServletRequest multipartRequest  =  (MultipartHttpServletRequest) request;
		    MultipartFile uploadFile = multipartRequest.getFile(UPLOAD_FILE_NAME);
		    if (uploadFile == null) {
                return ajaxHTML(Status.error,"上传失败：文件为空",null);
            }
            if(uploadFile.getSize()>2097152)        
            {
                return ajaxHTML(Status.error,"上传失败：文件大小不能超过2M",null);
            }
		    StorageFileVO vo = CloudStorageClient.uploadMultipartFile(uploadFile, cloudStorageDomain,cloudStorageAccountName, cloudStorageAccountKey, CloudStorageAccessType.PUBLIC);
		    if(null == vo){
		    	return ajaxHTML(Status.error,"上传失败",null);
		    }
	        
	        //返回数据
	        Map<String,String> data = new HashMap<String,String>();
	        data.put("fileName", vo.getFileName());
	        data.put("url", vo.getUrl());
	        return ajaxHTML(Status.success,"上传成功",data);
		}catch(Exception ex){
			String msg = "上传文件发生异常：" + ex.getMessage();
			logger.error(msg,ex);
			return ajaxHTML(Status.error,"上传失败",null);
		}
	}
	
	
	/**
	 * 文件上传 - 公开 - HTTP
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/uploadPublicFileByHttp.htm", method = RequestMethod.POST)
	public ModelAndView uploadPublicFileByHttp(HttpServletRequest request, HttpServletResponse response){
		MultipartHttpServletRequest multipartRequest  =  (MultipartHttpServletRequest) request;
	    MultipartFile uploadFile = multipartRequest.getFile(UPLOAD_FILE_NAME);
	    if (uploadFile == null) {
            return ajaxHTML(Status.error,"上传失败：文件为空",null);
        }
	    
	    //获取图片上传设置
	    SysUploadSet sysUploadSet = sysUploadSetService.getSysUploadSet();
	    
	    try {
	    	//1.文件存储在临时目录上
			String fileName = uploadFile.getOriginalFilename();
		    //获取上传文件类型的扩展名,先得到.的位置，再截取从.的下一个位置到文件的最后，最后得到扩展名  
	        String fileExt = fileName.substring(fileName.lastIndexOf("."),fileName.length()).toLowerCase();  
			String tmpDir = System.getProperty("java.io.tmpdir");
			String tmpFilePath = tmpDir + File.separator + uuid() + fileExt;
			File tmpFile = new File(tmpFilePath);
			String returnFilePath  =null;
			try{
				uploadFile.transferTo(tmpFile);
				String fileType = "";
				int point = fileName.lastIndexOf(".");
				if (point != -1) {
					fileType = fileName.substring(point);
				}
				if (tmpFile.length() <= 76939047) {
					String time = String.valueOf(new Date().getTime());
					String saveFileName = time + (int) (Math.random() * 100) + fileType;
					String realPath = this.getRealyPath(sysUploadSet.getPublicRoot(),request);
					Date now = new Date();
					String subDir = DateUtil.formatDate(now, "yyyyMMdd");
					realPath = realPath + File.separator + subDir;
					File dir = new File(realPath);
					boolean createSuccess = false;
					if (!dir.exists()) {
						createSuccess = dir.mkdirs();
					} else {
						createSuccess = true;
					}
					if (createSuccess) {
						String destPath = realPath + File.separator + saveFileName;
						File destFile = new File(destPath);
						this.upload(tmpFile, destFile);
					} else {
						saveFileName = null;
					}
					returnFilePath= "/" + subDir + "/" + saveFileName;
				} else {
					throw new Exception("文件大小超出限制");
				}
			}catch(Exception ex){
				String msg = "上传临时文件失败:"+ex.getMessage();
				logger.error(msg,ex);
			}finally{
				FileUtils.deleteQuietly(tmpFile);
			}
	    	
	    	Map<String, String>  map  = new HashMap<String, String>();
	    	String name =uploadFile.getOriginalFilename();
	    	map.put("path", returnFilePath);
	    	map.put("fileName", name);
	    	return ajaxHTML(Status.success, "上传成功", map);
		} catch (Exception e) {
			e.printStackTrace();
			String msg   = "上传文件失败："+e.getMessage();
			logger.info("=========="+msg);
			return ajaxHTML(Status.error,msg,null);
		}
	}
	
	/**
	 * 文件上传 - 公开 - HTTP - 保存至sys_upload_file表
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/uploadPhotoSave.htm", method = RequestMethod.POST)
	public ModelAndView uploadPublicFileByHttpSave(SysUploadFileForm model, HttpServletRequest request, HttpServletResponse response){
		MultipartHttpServletRequest multipartRequest  =  (MultipartHttpServletRequest) request;
	    MultipartFile uploadFile = multipartRequest.getFile(UPLOAD_FILE_NAME);
	    if (uploadFile == null) {
            return ajaxHTML(Status.error,"上传失败：文件为空",null);
        }
	    
	    //获取图片上传设置
	    SysUploadSet sysUploadSet = sysUploadSetService.getSysUploadSet();
	    
	    try {
	    	//1.文件存储在临时目录上
			String fileName = uploadFile.getOriginalFilename();
		    //获取上传文件类型的扩展名,先得到.的位置，再截取从.的下一个位置到文件的最后，最后得到扩展名  
	        String fileExt = fileName.substring(fileName.lastIndexOf("."),fileName.length()).toLowerCase();  
			String tmpDir = System.getProperty("java.io.tmpdir");
			String tmpFilePath = tmpDir + File.separator + uuid() + fileExt;
			File tmpFile = new File(tmpFilePath);
			String returnFilePath = null;
			try{
				uploadFile.transferTo(tmpFile);
				String fileType = "";
				int point = fileName.lastIndexOf(".");
				if (point != -1) {
					fileType = fileName.substring(point);
				}
				if (tmpFile.length() <= 76939047) {
					String time = String.valueOf(new Date().getTime());
					String saveFileName = time + (int) (Math.random() * 100) + fileType;
					String realPath = this.getRealyPath(sysUploadSet.getPublicRoot(),request);
					Date now = new Date();
					String subDir = DateUtil.formatDate(now, "yyyyMMdd");
					realPath = realPath + File.separator + subDir;
					File dir = new File(realPath);
					boolean createSuccess = false;
					if (!dir.exists()) {
						createSuccess = dir.mkdirs();
					} else {
						createSuccess = true;
					}
					if (createSuccess) {
						String destPath = realPath + File.separator + saveFileName;
						File destFile = new File(destPath);
						this.upload(tmpFile, destFile);
					} else {
						saveFileName = null;
					}
					returnFilePath= "/" + subDir + "/" + saveFileName;
				} else {
					throw new Exception("文件大小超出限制");
				}
			}catch(Exception ex){
				String msg = "上传临时文件失败:"+ex.getMessage();
				logger.error(msg,ex);
			}finally{
				FileUtils.deleteQuietly(tmpFile);
			}
	    	
	    	Map<String, String>  map  = new HashMap<String, String>();
	    	String name = uploadFile.getOriginalFilename();
	    	map.put("path", returnFilePath);
	    	map.put("fileName", name);
	    	
	    	String url = model.getUrl();
	    	
	    	if(StringUtils.isBlank(url)){
	    		// 保存至sys_upload_file表
		    	SysUploadFile sysUploadFile = new SysUploadFile();
		    	sysUploadFile.setObjectId(model.getObjectId());
		    	sysUploadFile.setObjectType(model.getObjectType());
		    	sysUploadFile.setName(fileName);
		    	sysUploadFile.setFileName(fileName);
		    	sysUploadFile.setUrl(returnFilePath);
		    	sysUploadFile.setLocation(model.getLocation());
	    		sysUploadFileService.add(sysUploadFile);
	    	}else{
	    		SysUploadFile sysUploadFileDB = sysUploadFileService.getSysUploadFileByUrl(url);
	    		sysUploadFileDB.setFileName(fileName);
	    		sysUploadFileDB.setUrl(returnFilePath);
	    		sysUploadFileService.update(sysUploadFileDB);
	    	}
	    	
	    	return ajaxHTML(Status.success, "上传成功", map);
		} catch (Exception e) {
			e.printStackTrace();
			String msg   = "上传文件失败："+e.getMessage();
			logger.info("=========="+msg);
			return ajaxHTML(Status.error,msg,null);
		}
	}
	
	@RequestMapping(value = "/ajaxFileUpload.htm",method = RequestMethod.POST)
	public ModelAndView ajaxFileUpload(@RequestParam("maxSize") Integer MaxSize,HttpServletRequest request, HttpServletResponse response){
		try{
			 MultipartHttpServletRequest  multipartRequest= (MultipartHttpServletRequest) request;
			 MultipartFile uploadFile = multipartRequest.getFile(UPLOAD_FILE_NAME);
			 if(uploadFile == null){
				 return ajaxHTML(Status.error,"上传失败：文件为空",null);
			 }
			 if(uploadFile.getSize() > MaxSize && MaxSize != 0){
				 return ajaxHTML(Status.error,"上传失败：文件为空",null);
			 }
			 //获取图片上传设置
			 SysUploadSet sysUploadSet = sysUploadSetService.getSysUploadSet();
			 String fileName = uploadFile.getOriginalFilename();
			 String fileExt = fileName.substring(fileName.indexOf("."), fileName.length()).toLowerCase();
			 String tmpDir = System.getProperty("java.io.tmpdir");
			 String tmpFilePath = tmpDir + File.separator + uuid() + fileExt;
			 File tmpFile = new File(tmpFilePath);
			 String returnFilePath = "";
			 String saveFileName = "";
			try {
				uploadFile.transferTo(tmpFile);
				String time = String.valueOf(new Date().getTime());
				saveFileName = time + (int) (Math.random() * 100) + fileExt;
				String realPath = this.getRealyPath(sysUploadSet.getPublicRoot(), request);
				String subDir = DateUtil.formatDate(new Date(), "yyyyMMdd");
				realPath = realPath + File.separator + subDir;
				File dirFile = new File(realPath);
				if(!dirFile.exists()){
					dirFile.mkdirs();
				}
				String savePath = realPath + File.separator + saveFileName;
				File savaFile = new File(savePath);
				this.upload(tmpFile, savaFile);
				returnFilePath= "/" + subDir + "/" + saveFileName;
				
			} catch (Exception e){
				e.printStackTrace();
			}finally{
				FileUtils.deleteQuietly(tmpFile);
			}
			Map<String, String> map = new HashMap<String, String>();
			map.put("path", returnFilePath);
			map.put("fileName", saveFileName);
			return ajaxHTML(Status.success, "上传成功", map);
		}catch(Exception e){
			String msg = "上传图片发生异常：" +e.getMessage();
			logger.error(msg, e);
			return ajaxHTML(Status.error,"上传失败", null);
		}
	}
	
	/**
	 * 文件上传 - 非公开 - HTTP
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/uploadPrivateFileByHttp.htm", method = RequestMethod.POST)
	public ModelAndView uploadPrivateFileByHttp(HttpServletRequest request, HttpServletResponse response){
		MultipartHttpServletRequest multipartRequest  =  (MultipartHttpServletRequest) request;
	    MultipartFile uploadFile = multipartRequest.getFile(UPLOAD_FILE_NAME);
	    if (uploadFile == null) {
            return ajaxHTML(Status.error,"上传失败：文件为空",null);
        }
	    File tmpFile = null;
	    
	    //获取图片上传设置
	    SysUploadSet sysUploadSet = sysUploadSetService.getSysUploadSet();
	    
	    try {
	    	//1.文件存储在临时目录上
			String fileName = uploadFile.getOriginalFilename();
		    //获取上传文件类型的扩展名,先得到.的位置，再截取从.的下一个位置到文件的最后，最后得到扩展名  
	        String fileExt = fileName.substring(fileName.lastIndexOf("."),fileName.length()).toLowerCase();  
			String tmpDir = System.getProperty("java.io.tmpdir");
			String tmpFilePath = tmpDir + File.separator + uuid() + fileExt;
			tmpFile = new File(tmpFilePath);
			
			//保存临时文件
			uploadFile.transferTo(tmpFile);
			
			//保存到物理磁盘上
			String fileType = "";
			int point = fileName.lastIndexOf(".");
			if (point != -1) {
				fileType = fileName.substring(point);
			}
			String time = String.valueOf(new Date().getTime());
			String saveFileName = time + (int) (Math.random() * 100) + fileType;
			
			Date now = new Date();
			String subDir = DateUtil.formatDate(now, "yyyyMMdd");
			String destPath = sysUploadSet.getPrivateRoot() + File.separator + subDir;
			File destDir = new File(destPath);
			if (!destDir.exists()) {
				destDir.mkdirs();
			}
			destPath = destPath + File.separator + saveFileName;
			File destFile = new File(destPath);
			this.upload(tmpFile, destFile);
	    	
	    	//返回数据
	    	Map<String, String>  map  = new HashMap<String, String>();
	    	String name =uploadFile.getOriginalFilename();
			String returnPath = File.separator + subDir + File.separator + saveFileName;
	    	map.put("path", returnPath);
	    	map.put("fileName", name);
	    	map.put("extend", fileExt.substring(1));
	    	map.put("size", String.valueOf(uploadFile.getSize()));
	    	return ajaxHTML(Status.success, "上传成功", map);
		} catch (Exception e) {
			e.printStackTrace();
			String msg   = "上传文件失败："+e.getMessage();
			logger.info("=========="+msg);
			return ajaxHTML(Status.error,msg,null);
		} finally{
			FileUtils.deleteQuietly(tmpFile);
		}
	}
	
	/**
	 * 文件下载 - 非公开 - HTTP
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/downloadLocalFileByPath.htm", method = RequestMethod.GET)
	public void downloadLocalFileByPath(HttpServletRequest request,HttpServletResponse response) {
		
		//获取图片上传设置
	    SysUploadSet sysUploadSet = sysUploadSetService.getSysUploadSet();
		
		//如果有权限就下载
		String fileName = request.getParameter("fileName");
		String filePath = request.getParameter("filePath");
		String realFilePath = sysUploadSet.getPrivateRoot() + filePath;
		this.writeToClient(fileName, realFilePath, request, response);
	}
}
